#include <stdlib.h>
#include <windows.h>

#pragma warning (disable:4800) // CSN-12948 - Upgrade to VS2012

#include "lib.h"
#include "opts.h"
#include "winsock2.h"
#include "dir.h"
#include "pathname.h"

#define INIFILE				L"server.ini"
#define DEFAULT_CURRENCY	L"USD"

String ServerOpts::dbdsn;
String ServerOpts::dblogin;
String ServerOpts::dbpasswd;
String ServerOpts::smtphost;
String ServerOpts::smtpsubject;
String ServerOpts::smtpto;
String ServerOpts::listservEmail;
String ServerOpts::casinoName;
String ServerOpts::baseName;
String ServerOpts::appName;
String ServerOpts::currency;
int32  ServerOpts::casinoId = 0;
bool8 ServerOpts::bAllowTesting = false;
bool8  ServerOpts::bSaveFunData = true;
bool8 ServerOpts::bUseExternalWallet = false;		 // default to false
bool8 ServerOpts::bUseDBWallet = true;				 // default to true
int32  ServerOpts::nNumListeners = SOMAXCONN;        // kharmon.  12-01-05.  #7665.  Adding option to control the size of the socket listener queue.
String ServerOpts::logDirectory;					 // cgc. 26/08/2009. New log in text file	
int32  ServerOpts::logAppLevel = 1;					 // cgc. 16/10/2009. Log trace level
int32  ServerOpts::serverId = 1;				
int32  ServerOpts::skinId = 1;
String ServerOpts::intAPIHost;
String ServerOpts::intAPIUser;
String ServerOpts::intAPIPassword;
String ServerOpts::intAPIProduct;

String ServerOpts::patchPackagesBasePath;
String ServerOpts::patchPackagesPath;
String ServerOpts::patchNewPackagesPath;
String ServerOpts::patchPackagesList;

void 
ServerOpts::load(const String& iniFile, const String& serverName )
{
    // Get File Names
    String sIniFileName, sServerName;
	if( iniFile == String::emptyString )
	{
		GetOptFileNames( sIniFileName, sServerName );
	}
	else
	{
		sIniFileName = iniFile;
		sServerName = serverName;
	}

	// CSN-13943 - Store app (exe) name so that Service Control can read it
	appName = sServerName;

    // Get options
	getStrOpt("Database", "dsn", "dsn", dbdsn, sIniFileName);
	getStrOpt("Database", sServerName, "", dblogin, sIniFileName);
	getStrOpt("Database", dblogin, "", dbpasswd, sIniFileName);

	getStrOpt("SMTP", "host", "127.0.0.1", smtphost, sIniFileName);
	getStrOpt("SMTP", "subject", "", smtpsubject, sIniFileName);
	getStrOpt("SMTP", "to", "", smtpto, sIniFileName);
	getStrOpt("SMTP", "listserv", "", listservEmail, sIniFileName);

	getStrOpt("Casino", "name", "", casinoName, sIniFileName);
	casinoId = getInt32Opt("Database", "casinoid", 0, sIniFileName);

	// CSN-13727 - Read player currency from config file. If the currency is
	//             not found or is 'FUN', replace it by the default currency.
	getStrOpt("Casino", "currency", DEFAULT_CURRENCY, currency, sIniFileName);
	if (currency == "FUN")
		currency = DEFAULT_CURRENCY;
	
	getStrOpt("Base", "name", "base", baseName, sIniFileName);

	if ( getInt32Opt("Testing", "AllowTesting", 0, sIniFileName) )
	{
		bAllowTesting = true;
	}
	else
	{
		bAllowTesting = false;
	}

	if ( getInt32Opt("Options", "SaveFunData", 1, sIniFileName) )
	{
		bSaveFunData = true;
	}
	else
	{
		bSaveFunData = false;
	}
	
    // kharmon.  12-01-05.  #7665.  Adding option to control the size of the socket listener queue.
    nNumListeners = getInt32Opt("Options", "NumListeners", SOMAXCONN, sIniFileName);

	
	// CSN-8892: Switch on/off wallet (default to false)
	if ( getInt32Opt("Options", "UseExternalWallet", 0, sIniFileName) )
	{
		bUseExternalWallet = true;
	}
	else
	{
		bUseExternalWallet = false;
	}

	// CSN-8892: Switch on/off database (default to true)
	if ( getInt32Opt("Options", "UseDatabaseWallet", 1, sIniFileName) )
	{
		bUseDBWallet = true;
	}
	else
	{
		bUseDBWallet = false;
	}

	// bUseDBWallet and bUseExternalWallet can't be false at the same time
	if (!bUseExternalWallet && !bUseDBWallet)
	{
		bUseDBWallet = true;
	}

	// cgc. 26/08/2009. New log in text file. Read log directory
	getStrOpt("LOG", "Directory", ".\\Log\\", logDirectory, sIniFileName);
	PathName pathLogDirectory;
	pathLogDirectory.set(logDirectory);
	// If directory does not exist, create it. If error, application path directory
	if (!Directory::isDirectory(pathLogDirectory))
	{
		if (!Directory::makeAll(pathLogDirectory))
		{
			logDirectory = ".\\Log\\";
			pathLogDirectory.set(logDirectory);
			if (!Directory::isDirectory(pathLogDirectory))
			{	
				if (!Directory::make(pathLogDirectory))
				{
					logDirectory = ".\\";
				}
			}
		}
	}
	if (logDirectory.substring(logDirectory.getLength()-1,1) != "\\")
		logDirectory = logDirectory + String("\\");

	// cgc. 16/10/2009. Log trace level
	logAppLevel = getInt32Opt("LOG", "LogLevel", 3, sIniFileName);

	serverId = getInt32Opt("CASINO", "serverId", 1, sIniFileName);

	// CSN-7075: New Authentication
	getStrOpt("INTAPI", "Host", "", intAPIHost, sIniFileName);
	getStrOpt("INTAPI", "User", "", intAPIUser, sIniFileName);
	getStrOpt("INTAPI", "Password", "", intAPIPassword, sIniFileName);
	// CSN-8893: Product ID for INTAPI
	// TODO: This is a temporary Product and it should be replaced
	getStrOpt("INTAPI", "Product", "POKER", intAPIProduct, sIniFileName);

	// CSN-14503: Paths for Patch service
	getStrOpt("Patch", "PackagesPath", "", patchPackagesBasePath, sIniFileName);
	int length = patchPackagesBasePath.getLength();

	if (length == 0)
	{
		TCHAR here[MAX_PATH + 1];
		length = GetModuleFileName(NULL, here, MAX_PATH);
		patchPackagesBasePath = here;
		patchPackagesBasePath = patchPackagesBasePath.substring(0, patchPackagesBasePath.reverseFind("\\"));
	}

	if (length > 0 && patchPackagesBasePath.substring(length -1, 1) != "\\")
		patchPackagesBasePath += "\\";

	patchPackagesPath    = patchPackagesBasePath + String("pkgs\\");
	patchNewPackagesPath = patchPackagesBasePath + String("NewPackages\\");
	patchPackagesList    = patchPackagesBasePath + String("pkglist.ini");
}

void
ServerOpts::getStrOpt(const String& Section, const String& Key, const String& Default,
	String& Dest, const String& IniFile)
{
	int32 len;

	len = GetPrivateProfileStringW(Section, Key, Default,
		Dest.getBuffer(1024), 1024, IniFile);

	Dest.releaseBuffer();

	Dest.trim();
}

int32
ServerOpts::getInt32Opt(const String& Section, const String& Key, int32 Default, const String& IniFile)
{
	return (int32)GetPrivateProfileIntW(Section, Key, (INT)Default, IniFile);
}


void 
ServerOpts::GetOptFileNames( String& sIniFileName, String& sServerName )
{
    // Get full module file name
    uint16* pBuffer = sIniFileName.getBuffer( MAX_PATH );
	GetModuleFileNameW(NULL, pBuffer, MAX_PATH);
    sIniFileName.releaseBuffer();
    
    // Strip off the name of the exe
    uint32 n = sIniFileName.reverseFind( String::Character('\\') );
    
    // If we didn't find a \ at all, just copy the entire string
    if ( n == String::NPOS )
    {
        n = 0;
    }

    // Copy server name
    sServerName = sIniFileName.substring( n+1 );

    // Append the ini file name onto the path we have extracted so far
    sIniFileName.setChar( n+1, '\0' );
    sIniFileName += INIFILE;

    // Remove the "." in the server name
    if ( (n = sServerName.reverseFind( String::Character('.'))) != String::NPOS )
    {
        sServerName.setChar( n, '\0' );
    }
}


// check if the casino name is used in debug/QA environment
bool ServerOpts::IsDebugCasinoName() 
{
	String casino_name_upper = casinoName;
	casino_name_upper.toUpper();

	//if the casino name starts with the following, allow debug spins mode
	//in a release build
	// CGC 20100624. Addin "INT" so that it works on integration environment
	int u = casino_name_upper.find("INT",0);
	int w = casino_name_upper.find("QA",0);
	int x = casino_name_upper.find("DEV",0);
	int y = casino_name_upper.find("STAGING",0);
	int z = casino_name_upper.find("DEBUG",0);

	return w != -1 || x != -1 || y != -1 || z != -1 || u != -1;
}
